// SET MESSAGE (WIN/LOSE) function setMessage(text, status) { messageEl.textContent = text; messageEl.className = status; } // Simple Blackjack implementation const SUITS = ['♠', '♥', '♦', '♣']; const RANKS = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']; // DOM const dealerHandEl = document.getElementById('dealer-hand'); const playerHandEl = document.getElementById('player-hand'); const dealerValueEl = document.getElementById('dealer-value'); const playerValueEl = document.getElementById('player-value'); const balanceEl = document.getElementById('balance'); const betInput = document.getElementById('bet-input'); const betBtn = document.getElementById('bet-btn'); const currentBetEl = document.getElementById('current-bet'); const hitBtn = document.getElementById('hit'); const standBtn = document.getElementById('stand'); const doubleBtn = document.getElementById('double'); const newRoundBtn = document.getElementById('new-round'); const messageEl = document.getElementById('message'); // TOP UP DOM Elements - HANDLED IN HTML.PHP // const topUpBtn = document.getElementById('top-up-btn'); // const topUpModal = document.getElementById('top-up-modal'); // const topUpClose = document.getElementById('top-up-close'); // const topUpInput = document.getElementById('top-up-input'); // const topUpConfirm = document.getElementById('top-up-confirm'); // const topUpHistoryEl = document.getElementById('top-up-history'); // const topUpBalanceEl = document.getElementById('top-up-balance'); // Game variables let deck = []; let dealer = []; let player = []; let dealerHidden = true; let balance = 0; let currentBet = 0; let inRound = false; // TOP UP variables - HANDLED IN HTML.PHP // let topUpAmount = 0; // let topUpHistory = []; // Initialize balance from global gameBalance if (typeof gameBalance !== 'undefined') { balance = gameBalance; } else { balance = 1000; } function makeDeck() { deck = []; for (const s of SUITS) { for (const r of RANKS) { deck.push({ suit: s, rank: r }); } } } function shuffle() { for (let i = deck.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [deck[i], deck[j]] = [deck[j], deck[i]]; } } function cardValue(card) { const r = card.rank; if (r === 'A') return [1, 11]; if (['J', 'Q', 'K'].includes(r)) return [10]; return [parseInt(r, 10)]; } function handValues(hand) { let totals = [0]; for (const c of hand) { const vals = cardValue(c); const newTotals = []; for (const t of totals) { for (const v of vals) { newTotals.push(t + v); } } totals = Array.from(new Set(newTotals)); } const valid = totals.filter(t => t <= 21); if (valid.length) return Math.max(...valid); return Math.min(...totals); } function renderHand(el, hand, hideFirst = false) { el.innerHTML = ''; hand.forEach((c, i) => { const div = document.createElement('div'); div.className = 'card' + (c.suit === '♥' || c.suit === '♦' ? ' red' : ''); if (hideFirst && i === 0) { div.className = 'card back'; div.textContent = 'TERSEMBUNYI'; } else { const top = document.createElement('div'); top.textContent = c.rank + ' ' + c.suit; const bot = document.createElement('div'); bot.style.alignSelf = 'flex-end'; bot.textContent = c.rank + ' ' + c.suit; div.appendChild(top); div.appendChild(bot); } el.appendChild(div); }); } function updateUI() { renderHand(dealerHandEl, dealer, dealerHidden); renderHand(playerHandEl, player, false); dealerValueEl.textContent = dealerHidden ? '??' : 'Nilai: ' + handValues(dealer); playerValueEl.textContent = 'Nilai: ' + handValues(player); balanceEl.textContent = balance.toLocaleString('id-ID'); currentBetEl.textContent = currentBet.toLocaleString('id-ID'); // updateTopUpBalance(); // Redundant } function updateBalanceOnServer() { fetch('html.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'update_balance=' + balance }) .then(response => { if (response.headers.get('content-type')?.includes('application/json')) { return response.json(); } return { status: 'success' }; }) .then(data => { if (data.balance !== undefined) { balance = data.balance; gameBalance = data.balance; } }) .catch(err => console.log('Balance update sent', err)); } function startRound() { if (inRound) return; const bet = Number(betInput.value) || 0; if (bet <= 0 || bet > balance) { alert('BANK TIDAK CUKUP!'); return; } currentBet = bet; balance -= bet; gameBalance = balance; inRound = true; dealerHidden = true; setMessage('', ''); makeDeck(); shuffle(); dealer = [deck.pop(), deck.pop()]; player = [deck.pop(), deck.pop()]; updateUI(); // NATURAL BLACKJACK if (handValues(player) === 21) { dealerHidden = false; updateUI(); const dealerVal = handValues(dealer); if (dealerVal === 21) { balance += currentBet; gameBalance = balance; setMessage('Tie (seri).', ''); } else { const payout = Math.floor(currentBet * 2.5); balance += payout; gameBalance = balance; setMessage('Blackjack! You Win!', 'win'); } inRound = false; currentBet = 0; updateUI(); updateBalanceOnServer(); } } function playerHit() { if (!inRound) return; player.push(deck.pop()); updateUI(); if (handValues(player) > 21) { dealerHidden = false; setMessage('Bust! You Lose!', 'lose'); inRound = false; currentBet = 0; gameBalance = balance; updateUI(); updateBalanceOnServer(); } } function playerStand() { if (!inRound) return; dealerHidden = false; while (handValues(dealer) < 17) { dealer.push(deck.pop()); } const pv = handValues(player); const dv = handValues(dealer); if (dv > 21 || pv > dv) { balance += currentBet * 2; gameBalance = balance; setMessage('You Win!', 'win'); } else if (pv === dv) { balance += currentBet; gameBalance = balance; setMessage('Tie (seri).', ''); } else { setMessage('You Lose!', 'lose'); } inRound = false; currentBet = 0; updateUI(); updateBalanceOnServer(); } function playerDouble() { if (!inRound) return; if (balance < currentBet) { alert('Bank tidak cukup untuk double.'); return; } balance -= currentBet; gameBalance = balance; currentBet *= 2; player.push(deck.pop()); updateUI(); if (handValues(player) > 21) { dealerHidden = false; setMessage('Bust! You Lose!', 'lose'); inRound = false; currentBet = 0; updateUI(); updateBalanceOnServer(); return; } playerStand(); } // TOP UP FUNCTIONS - HANDLED IN HTML.PHP /* function showTopUpModal() { topUpModal.style.display = 'block'; if(topUpInput) topUpInput.value = ''; updateTopUpHistory(); } function hideTopUpModal() { topUpModal.style.display = 'none'; } function processTopUp() { const amount = Number(topUpInput.value) || 0; if (amount <= 0) { alert('Masukkan jumlah top up yang valid!'); return; } if (amount > 1000000) { alert('Maksimal top up adalah 1.000.000!'); return; } balance += amount; gameBalance = balance; topUpAmount += amount; topUpHistory.push({ amount: amount, date: new Date().toLocaleString('id-ID'), balanceAfter: balance }); updateUI(); updateTopUpHistory(); setMessage(`Top up berhasil! +${amount.toLocaleString('id-ID')}`, 'win'); hideTopUpModal(); } function updateTopUpHistory() { if (!topUpHistoryEl) return; topUpHistoryEl.innerHTML = ''; if (topUpHistory.length === 0) { topUpHistoryEl.innerHTML = '

Belum ada riwayat top up

'; return; } const recentHistory = topUpHistory.slice(-5).reverse(); recentHistory.forEach(record => { const historyItem = document.createElement('div'); historyItem.className = 'history-item'; historyItem.innerHTML = `
+${record.amount.toLocaleString('id-ID')}
${record.date}
Saldo: ${record.balanceAfter.toLocaleString('id-ID')}
`; topUpHistoryEl.appendChild(historyItem); }); } function updateTopUpBalance() { if (topUpBalanceEl) { topUpBalanceEl.textContent = `Total Top Up: ${topUpAmount.toLocaleString('id-ID')}`; } } */ // EVENT LISTENERS betBtn.addEventListener('click', function (e) { startRound(); }); hitBtn.addEventListener('click', playerHit); standBtn.addEventListener('click', playerStand); doubleBtn.addEventListener('click', playerDouble); newRoundBtn.addEventListener('click', function () { if (inRound && !confirm('Masih dalam ronde. Reset?')) return; balance = 1000; gameBalance = 1000; currentBet = 0; inRound = false; dealer = []; player = []; deck = []; dealerHidden = true; setMessage('Bank di-reset.', ''); updateUI(); updateBalanceOnServer(); }); // TOP UP EVENT LISTENERS - HANDLED IN HTML.PHP /* if (topUpBtn) { topUpBtn.addEventListener('click', showTopUpModal); } if (topUpClose) { topUpClose.addEventListener('click', hideTopUpModal); } if (topUpConfirm) { topUpConfirm.addEventListener('click', processTopUp); } window.addEventListener('click', (e) => { if (e.target === topUpModal) { hideTopUpModal(); } }); */ // KEYBOARD window.addEventListener('keydown', e => { if (e.key === 'h') playerHit(); if (e.key === 's') playerStand(); if (e.key === 'd') playerDouble(); if (e.key === 'Enter') startRound(); /* if (e.ctrlKey && e.key === 't') { e.preventDefault(); showTopUpModal(); } */ }); // INITIALIZATION updateUI(); // updateTopUpHistory(); // updateTopUpBalance();